/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.service.core.impl;

import com.blandware.atleap.common.util.PartialCollection;
import com.blandware.atleap.common.util.QueryInfo;
import com.blandware.atleap.model.core.ContentField;
import com.blandware.atleap.model.core.ContentFieldValue;
import com.blandware.atleap.model.core.ContentLocale;
import com.blandware.atleap.model.core.Localizable;
import com.blandware.atleap.persistence.core.ContentFieldDAO;
import com.blandware.atleap.persistence.core.ContentFieldValueDAO;
import com.blandware.atleap.persistence.core.ContentLocaleDAO;
import com.blandware.atleap.persistence.core.LocalizableDAO;
import com.blandware.atleap.service.core.ContentFieldManager;
import com.blandware.atleap.service.exception.BeanAlreadyExistsException;
import com.blandware.atleap.service.exception.BeanNotFoundException;
import com.blandware.atleap.service.exception.ContentLocaleNotFoundException;
import com.blandware.atleap.service.exception.OwnerNotFoundException;

import java.util.List;

/**
 * <p>Implementation of ContentFieldManager</p>
 * <p><a href="ContentFieldManagerImpl.java.html"><i>View Source</i></a>
 * </p>
 *
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.22 $ $Date: 2007/04/03 19:27:21 $
 */
public class ContentFieldManagerImpl extends BaseManagerImpl implements ContentFieldManager {

    /**
     * Localizable DAO
     */
	protected LocalizableDAO localizableDAO;
    /**
     * Content field value DAO
     */
	protected ContentFieldValueDAO contentFieldValueDAO;
    /**
     * Content field DAO
     */
	protected ContentFieldDAO contentFieldDAO;
    /**
     * Content locale DAO
     */
	protected ContentLocaleDAO contentLocaleDAO;

    /**
     * Sets DAO for operating with localizables
     *
     * @param localizableDAO the DAO to set
     */
	public void setLocalizableDAO(LocalizableDAO localizableDAO) {
		this.localizableDAO = localizableDAO;
	}

    /**
     * Sets DAO for operating with content field values
     *
     * @param contentFieldValueDAO the DAO to set
     */
	public void setContentFieldValueDAO(ContentFieldValueDAO contentFieldValueDAO) {
		this.contentFieldValueDAO = contentFieldValueDAO;
	}

    /**
     * Sets DAO for operating with content fields
     *
     * @param contentFieldDAO the DAO to set
     */
	public void setContentFieldDAO(ContentFieldDAO contentFieldDAO) {
		this.contentFieldDAO = contentFieldDAO;
	}

    /**
     * Sets DAO for operating with content locales
     *
     * @param contentLocaleDAO the DAO to set
     */
	public void setContentLocaleDAO(ContentLocaleDAO contentLocaleDAO) {
		this.contentLocaleDAO = contentLocaleDAO;
	}

	//  F I E L D S

	//~ CRUD Methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#createContentField(com.blandware.atleap.model.core.ContentField, java.lang.Long)
	 */
	public Long createContentField(ContentField contentField, Long ownerId) throws BeanNotFoundException, BeanAlreadyExistsException {

		if ( log.isDebugEnabled() ) {
			log.debug("Creating new field...");
		}

		Localizable localizable = null;
		localizable = localizableDAO.retrieveLocalizable(ownerId);

		if ( localizable == null ) {
			String errorMessage = "No localizable with ID=" + ownerId + "could be found";
			if ( log.isErrorEnabled() ) {
				log.error(errorMessage);
			}
			throw new OwnerNotFoundException(errorMessage);
		}

		if ( contentFieldDAO.hasDuplicates(contentField, ownerId) ) {
			throw new BeanAlreadyExistsException("Content field with the same identifier already exists on owner with ID=" + ownerId);
		}

		Long fieldId = contentFieldDAO.createContentField(contentField, localizable);

		if ( log.isDebugEnabled() ) {
			log.debug("ContentField has been created successfully. Its ID is " + fieldId);
		}
		return fieldId;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#retrieveContentField(java.lang.Long)
	 */
	public ContentField retrieveContentField(Long contentFieldId) {
		ContentField field = null;
		field = contentFieldDAO.retrieveContentField(contentFieldId);
		return field;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#updateContentField(com.blandware.atleap.model.core.ContentField, java.lang.Long)
	 */
	public void updateContentField(ContentField contentField, Long localizableId) throws BeanNotFoundException, BeanAlreadyExistsException {

		// remove field from cache in order to prevent Hibernate from assigning new version number
		contentFieldDAO.removeFromCache(contentField);

		if ( log.isDebugEnabled() ) {
			log.debug("Updating contentField with ID=" + contentField.getId() + "...");
		}

		Localizable localizable = null;
		localizable = localizableDAO.retrieveLocalizable(localizableId);

		if ( localizable == null ) {
			String errorMessage = "No localizable with ID=" + localizableId + "could be found";
			if ( log.isErrorEnabled() ) {
				log.error(errorMessage);
			}
			throw new OwnerNotFoundException(errorMessage);
		}

		if ( contentFieldDAO.hasDuplicates(contentField, localizableId) ) {
			throw new BeanAlreadyExistsException("Content field with the same identifier already exists on owner with ID=" + localizableId);
		}

		// localizable contentField
		contentFieldDAO.updateContentField(contentField, localizable);


		if ( log.isDebugEnabled() ) {
			log.debug("ContentField was updated successfully.");
		}
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#deleteContentField(java.lang.Long)
	 */
	public void deleteContentField(Long contentFieldId) throws BeanNotFoundException {
		if ( log.isDebugEnabled() ) {
			log.debug("Deleting field with ID=" + contentFieldId);
		}

		ContentField contentField = contentFieldDAO.retrieveContentField(contentFieldId);
		if ( contentField == null ) {
			String errorMessage = "No contentField with ID=" + contentFieldId + "could be found";
			throw new BeanNotFoundException(errorMessage);
		}

		contentFieldDAO.deleteContentField(contentField);

		if ( log.isDebugEnabled() ) {
			log.debug("Contentfield has been deleted successfully");
		}
	}

	// ~ Additional methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#listContentFields(com.blandware.atleap.common.util.QueryInfo)
	 */
	public PartialCollection listContentFields(QueryInfo queryInfo) {
		return contentFieldDAO.listContentFields(queryInfo);
	}

	// ~ Finders ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#findContentFieldByLayoutDefinition(java.lang.String, java.lang.String)
	 */
	public ContentField findContentFieldByLayoutDefinition(String identifier, String definition) {
		return contentFieldDAO.findContentFieldByLayoutDefinition(identifier, definition);
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#findContentFieldByPageUri(java.lang.String, java.lang.String)
	 */
	public ContentField findContentFieldByPageUri(String identifier, String uri) {
		return contentFieldDAO.findContentFieldByPageUri(identifier, uri);
	}

    /**
     * @see com.blandware.atleap.service.core.ContentFieldManager#findIndexedContentFieldsByLayoutDefinition(String, String)
     */
    public List findIndexedContentFieldsByLayoutDefinition(String identifier, String definition) {
        return contentFieldDAO.findIndexedContentFieldsByLayoutDefinition(identifier, definition);
    }

    /**
     * @see com.blandware.atleap.service.core.ContentFieldManager#findIndexedContentFieldsByLayoutDefinitionAndLocale(java.lang.String, java.lang.String, java.lang.String)
     */
    public List findIndexedContentFieldsByLayoutDefinitionAndLocale(String identifier, String definition, String locale) {
        return contentFieldDAO.findIndexedContentFieldsByLayoutDefinitionAndLocale(identifier, definition, locale);
    }

    /**
     * @see com.blandware.atleap.service.core.ContentFieldManager#findIndexedContentFieldsByPageUri(String, String) 
     */
    public List findIndexedContentFieldsByPageUri(String identifier, String uri) {
        return contentFieldDAO.findIndexedContentFieldsByPageUri(identifier, uri);
    }

    /**
     * @see com.blandware.atleap.service.core.ContentFieldManager#findIndexedContentFieldsByPageUriAndLocale(java.lang.String, java.lang.String, java.lang.String)
     */
    public List findIndexedContentFieldsByPageUriAndLocale(String identifier, String uri, String locale) {
        return contentFieldDAO.findIndexedContentFieldsByPageUriAndLocale(identifier, uri, locale);
    }



	//  C O N T E N T    F I E L D    V A L U E

	//~ CRUD Methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#createContentFieldValue(com.blandware.atleap.model.core.ContentFieldValue, java.lang.Long, java.lang.String)
	 */
	public Long createContentFieldValue(ContentFieldValue contentFieldValue, Long fieldId, String localeIdentifier) throws BeanNotFoundException, BeanAlreadyExistsException {

		if ( log.isDebugEnabled() ) {
			log.debug("Creating new content field value...");
		}

		ContentField field = null;
		field = contentFieldDAO.retrieveContentField(fieldId);
		if ( field == null ) {
			String errorMessage = "No content field with ID=" + fieldId + "could be found";
			if ( log.isErrorEnabled() ) {
				log.error(errorMessage);
			}
			throw new OwnerNotFoundException(errorMessage);
		}

		ContentLocale contentLocale = null;
		contentLocale = contentLocaleDAO.retrieveContentLocale(localeIdentifier);

		if ( contentLocale == null ) {
			String errorMessage = "No content locale with identifier=" + localeIdentifier + "could be found";
			if ( log.isErrorEnabled() ) {
				log.error(errorMessage);
			}
			throw new ContentLocaleNotFoundException(errorMessage);
		}

		if ( contentFieldValueDAO.hasDuplicates(contentFieldValue, fieldId, localeIdentifier) ) {
			throw new BeanAlreadyExistsException("Content field value already exists for field with ID=" + fieldId + " and locale with identifier='" + localeIdentifier + "'");
		}

		Long contentFieldValueId = contentFieldValueDAO.createContentFieldValue(contentFieldValue, field, contentLocale);

		if ( log.isDebugEnabled() ) {
			log.debug("Content has been created successfully. Its ID is " + contentFieldValueId);
		}
		return contentFieldValueId;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#retrieveContentFieldValue(java.lang.Long)
	 */
	public ContentFieldValue retrieveContentFieldValue(Long contentFieldValueId) {
		ContentFieldValue contentFieldValue = null;
		contentFieldValue = contentFieldValueDAO.retrieveContentFieldValue(contentFieldValueId);
		return contentFieldValue;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#updateContentFieldValue(com.blandware.atleap.model.core.ContentFieldValue, java.lang.Long, java.lang.String)
	 */
	public void updateContentFieldValue(ContentFieldValue contentFieldValue, Long fieldId, String localeIdentifier) throws BeanNotFoundException, BeanAlreadyExistsException {

        // remove value from cache in order to prevent Hibernate from assigning new version number
		contentFieldValueDAO.removeFromCache(contentFieldValue);

		if ( log.isDebugEnabled() ) {
			log.debug("Updating field content with ID=" + contentFieldValue.getId() + "...");
		}

		ContentField field = null;
		field = contentFieldDAO.retrieveContentField(fieldId);
		if ( field == null ) {
			String errorMessage = "No field with ID=" + fieldId + "could be found";
			if ( log.isErrorEnabled() ) {
				log.error(errorMessage);
			}
			throw new OwnerNotFoundException(errorMessage);
		}

		ContentLocale contentLocale = null;
		contentLocale = contentLocaleDAO.retrieveContentLocale(localeIdentifier);
		if ( contentLocale == null ) {
			String errorMessage = "No content locale with identifier=" + localeIdentifier + "could be found";
			if ( log.isErrorEnabled() ) {
				log.error(errorMessage);
			}
			throw new ContentLocaleNotFoundException(errorMessage);
		}

		if ( contentFieldValueDAO.hasDuplicates(contentFieldValue, fieldId, localeIdentifier) ) {
			throw new BeanAlreadyExistsException("Content field value already exists for field with ID=" + fieldId + " and locale with identifier='" + localeIdentifier + "'");
		}
		
		// updating field content
		contentFieldValueDAO.updateContentFieldValue(contentFieldValue, field, contentLocale);

		if ( log.isDebugEnabled() ) {
			log.debug("ContentField content was updated successfully.");
		}
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#deleteContentFieldValue(java.lang.Long)
	 */
	public void deleteContentFieldValue(Long contentFieldValueId) throws BeanNotFoundException {
		if ( log.isDebugEnabled() ) {
			log.debug("Deleting field content with ID=" + contentFieldValueId);
		}

		ContentFieldValue contentFieldValue = contentFieldValueDAO.retrieveContentFieldValue(contentFieldValueId);
		if ( contentFieldValue == null ) {
			String errorMessage = "No contentFieldValue with ID=" + contentFieldValueId + "could be found";
			throw new BeanNotFoundException(errorMessage);
		}

		contentFieldValueDAO.deleteContentFieldValue(contentFieldValue);
		if ( log.isDebugEnabled() ) {
			log.debug("ContentField content has been deleted successfully");
		}
	}

	// ~ Additional methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#listContentFieldValues(com.blandware.atleap.common.util.QueryInfo)
	 */
	public PartialCollection listContentFieldValues(QueryInfo queryInfo) {
		return contentFieldValueDAO.listContentFieldValues(queryInfo);
	}

	// ~ Finders ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#findContentFieldValueByUriAndIdentifierAndLocale(java.lang.String, java.lang.String, java.lang.String)
	 */
	public ContentFieldValue findContentFieldValueByUriAndIdentifierAndLocale(String uri, String identifier, String localeIdentifier) {
		return contentFieldValueDAO.findContentFieldValueByUriAndIdentifierAndLocale(uri, identifier, localeIdentifier);
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#findContentFieldValueByDefinitionAndIdentifierAndLocale(java.lang.String, java.lang.String, java.lang.String)
	 */
	public ContentFieldValue findContentFieldValueByDefinitionAndIdentifierAndLocale(String definition, String identifier, String localeIdentifier) {
		return contentFieldValueDAO.findContentFieldValueByDefinitionAndIdentifierAndLocale(definition, identifier, localeIdentifier);
	}

    /**
     * @see com.blandware.atleap.service.core.ContentFieldManager#findContentFieldValueByLocalizableIdAndIdentifierAndLocale(java.lang.Long, java.lang.String, java.lang.String)
     */
    public ContentFieldValue findContentFieldValueByLocalizableIdAndIdentifierAndLocale(Long localizableId, String identifier, String localeIdentifier) {
        return contentFieldValueDAO.findContentFieldValueByLocalizableIdAndIdentifierAndLocale(localizableId, identifier, localeIdentifier);
    }

	/**
	 * @see com.blandware.atleap.service.core.ContentFieldManager#findContentFieldValueByContentFieldIdAndLocale(Long, String)
	 */
	public ContentFieldValue findContentFieldValueByContentFieldIdAndLocale(Long fieldId, String localeIdentifier) {
		ContentField field = retrieveContentField(fieldId);
		ContentLocale locale = contentLocaleDAO.retrieveContentLocale(localeIdentifier);
		return contentFieldValueDAO.findContentFieldValueByContentFieldAndLocale(field, locale);
	}


}

